﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace ReactiveCode.Linq
{
    using Observables;

    class Selection<T> : UnaryOperator<T, T>
    {
        Func<IObservable<T>, IObservable<bool>> _predicate;

        public Selection(IEnumerableObserver<T> observer, Func<IObservable<T>, IObservable<bool>> predicate)
            : base(observer)
        {
            Contract.Requires(predicate != null);
            _predicate = predicate;
        }

        protected override Entry OnAdded(IObservable<T> item)
        {
            var satisfies = _predicate(item).SkipWhile(s => !s).LatestContinuous();
            var subscription = satisfies.Subscribe(
                onNext: s =>
                {
                    if (s)
                        Observer.OnAdded(item);
                    else
                        Observer.OnRemoved(item);
                },
                onError: OnError);
            return new Entry
            {
                Remove = delegate
                {
                    if (satisfies.HasValue && satisfies.Value)
                        Observer.OnRemoved(item, -1);
                },
                Subscription = subscription
            };
        }
    }
}
